package com.xframework.gateway.filter;

import com.xframework.exception.BusinessException;
import com.xframework.redis.XRedisTemplate;
import com.xframework.security.model.SecurityAccount;
import com.xframework.security.util.Constant;
import com.xframework.security.util.JWTUtil;
import io.jsonwebtoken.Claims;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Map;

/**
 * 全局鉴权 过滤器
 */
@Component
public class SecurityGlobalFilter implements GlobalFilter, Ordered {

    public SecurityGlobalFilter() {
    }

    //过滤器逻辑
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String url = exchange.getRequest().getURI().getPath();
        System.out.println("我被过滤啦" + url);
        boolean flag = Boolean.FALSE;
        //跳过不需要验证的路径
        if (Constant.securityExcludeUrlPatterns != null) {
            for (String regex : Constant.securityExcludeUrlPatterns) {
                if (Constant.matches(regex, url)) {
                    flag = Boolean.TRUE;
                    break;
                }
            }
        }
        if (!flag) {
            //统一鉴权逻辑
            String securityToken = exchange.getRequest().getHeaders().getFirst(Constant.Authorization);
            if (securityToken != null) {
                Claims payload = JWTUtil.parserJWT(securityToken);
                if (payload != null) {
                    String applicationId = payload.getSubject();
                    Map<String, String> securityResourceUrlMap = XRedisTemplate.get(Constant.SECURITY_APPLICATION + Constant.UNDERLINE + applicationId, Map.class);
                    if (securityResourceUrlMap != null) {
                        if (securityResourceUrlMap.get(url) == null) {
                            flag = true;
                        }
                    }
                    if (!flag) {
                        String accountId = payload.getId();
                        SecurityAccount securityAccount = XRedisTemplate.get(Constant.SECURITY_ACCOUNT + Constant.UNDERLINE + applicationId + Constant.UNDERLINE + accountId, Constant.securityJwtExpiration, SecurityAccount.class);
                        if (Constant.securityJwtDelay) {
                            securityAccount.setAccountId(accountId);
                            securityAccount.setAccountName(payload.getAudience());
                            securityAccount.setApplicationId(applicationId);
                            securityToken = JWTUtil.createJWT(securityAccount);
                        }
                        String resourceUrls = securityAccount.getResourceUrls();
                        if (Constant.matches(resourceUrls, url)) {
                            flag = Boolean.TRUE;
                            exchange.getResponse().getHeaders().add(Constant.Authorization, securityToken);
                            exchange.getResponse().getHeaders().add(Constant.SECURITY_ACCOUNT, accountId);
                        }
                    }
                }
            }
        }
        if (flag) {
            return chain.filter(exchange);
        } else {
//            ServerHttpResponse resp = exchange.getResponse();
//            resp.setStatusCode(HttpStatus.UNAUTHORIZED);
//            resp.getHeaders().setContentType(MediaType.APPLICATION_JSON_UTF8);
//            RespData<String> respData = new RespData<String>(0, Constant.securityInvalid);
//            DataBuffer buffer = resp.bufferFactory().wrap(JSON.toJSONString(respData).getBytes(StandardCharsets.UTF_8));
//            return resp.writeWith(Flux.just(buffer));
            throw new BusinessException(Constant.securityInvalidMessage);
        }
    }

    //优先级   数值越小越高
    @Override
    public int getOrder() {
        return -9999;
    }

}
